﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace WellDone
{
    public partial class ScheduleControl : UserControl
    {
        private ObservableCollection<ServiceReferenceOpenRPOS.Schedule> ScheduleRecords = new ObservableCollection<ServiceReferenceOpenRPOS.Schedule>();
        public ObservableCollection<ServiceReferenceOpenRPOS.EmployeeRole> EmployeeRoleRecords = new ObservableCollection<ServiceReferenceOpenRPOS.EmployeeRole>();
        private int currentEmployeeID,currentScheduleTemplateID,currentSchedule=0;
        private DateTime currentDate;

        public ScheduleControl()
        {
            InitializeComponent();
        }

        private void initDisplay()
        {
            // Populate the first schedule record
            if (ScheduleRecords.Count > 0)
            {
                tpIn.IsEnabled = true;
                tpIn.Value = ScheduleRecords[currentSchedule].col_Start;
                tpOut.IsEnabled = true;
                tpOut.Value = ScheduleRecords[currentSchedule].col_Stop;
                cmbRole.IsEnabled = true;
                cbRecurrence.IsChecked = (ScheduleRecords[currentSchedule].col_RecurrenceType == 1);
                cbRecurrence.IsEnabled = true;
                lblSchedules.Content = (currentSchedule+1).ToString() + " of " + ScheduleRecords.Count.ToString();
                btnNextSchedule.Visibility = (currentSchedule+1<ScheduleRecords.Count) ? Visibility.Visible : Visibility.Collapsed;
                btnPrevSchedule.Visibility = (currentSchedule>0) ? Visibility.Visible : Visibility.Collapsed;
                btnDeleteSchedule.Visibility = Visibility.Visible;
                if (cmbRole.Items.Count > 0)
                {
                    if (EmployeeRoleRecords.Where(x => x.col_RoleID == ScheduleRecords[currentSchedule].col_RoleID).Count() != 0)
                        cmbRole.SelectedIndex = (EmployeeRoleRecords.Count > 0) ?
                            EmployeeRoleRecords.IndexOf(EmployeeRoleRecords.Where(x => x.col_RoleID == ScheduleRecords[currentSchedule].col_RoleID).First()) : 0;
                    else
                        cmbRole.SelectedIndex = 0;
                }
                tpIn.Focus();
            }
        }

        public void clearDisplay()
        {
            tpIn.IsEnabled = false;
            tpIn.Value = null;
            tpOut.IsEnabled = false;
            tpOut.Value = null;
            cmbRole.IsEnabled = false;
            cbRecurrence.IsChecked = false;
            cbRecurrence.IsEnabled = false;
            lblSchedules.Content = "N/A";
            btnNextSchedule.Visibility = Visibility.Collapsed;
            btnPrevSchedule.Visibility = Visibility.Collapsed;
            btnDeleteSchedule.Visibility = Visibility.Collapsed;
        }

        public void clearScheduleTemplateDisplay()
        {
            clearDisplay();
            btnAddSchedule.Visibility = Visibility.Collapsed;
            lblSchedules.Visibility = Visibility.Collapsed;
        }

        public void loadPreferences(bool clear)
        {
            ScheduleRecords.Clear();
            // Get employee schedule for that day
            foreach (ServiceReferenceOpenRPOS.Schedule sch in Globals.db.ScheduleRecords)
            {
                if (sch.col_EmployeeID == currentEmployeeID && sch.col_Start.Date == currentDate.Date && ((Globals.currentLogin.col_Manager && (sch.col_Preference||!clear)) || (sch.col_Preference && !Globals.currentLogin.col_Manager)))
                {
                    // This schedule record matches - update local data
                    ScheduleRecords.Add(sch);
                }
            }
            if (ScheduleRecords.Count > 0)
            {
                initDisplay();
            }
            else // If no records were found, disable the interface
            {
                clearDisplay();
            }
        }

        public void init(int employeeID, DateTime selectedDate)
        {
            currentEmployeeID = employeeID;
            currentDate = selectedDate;
            ScheduleRecords.Clear();
            IEnumerable<ServiceReferenceOpenRPOS.Schedule> query = Globals.db.ScheduleRecords.OrderBy(sch => sch.col_Start);

            // Reset the schedule template ID
            currentScheduleTemplateID = 0;
            // Set the date
            lblDate.Content = selectedDate.DayOfWeek.ToString().Substring(0, 3) + " (" + selectedDate.ToShortDateString().Remove(selectedDate.ToShortDateString().Length - 5) + ")"; 
            // Get employee schedule for that day
            foreach (ServiceReferenceOpenRPOS.Schedule sch in query)
            {
                if (sch.col_EmployeeID == employeeID && ((sch.col_Start.Date == selectedDate.Date) || (sch.col_Start.Date.DayOfWeek == selectedDate.Date.DayOfWeek && sch.col_RecurrenceType == 1)) &&
                    ((!sch.col_Preference && Globals.currentLogin.col_Manager) || (sch.col_Preference && !Globals.currentLogin.col_Manager)))
                {
                    // Reset the date for recurrence records
                    if (sch.col_RecurrenceType == 1)
                    {
                        sch.col_Start = sch.col_Start.AddDays((selectedDate.Date - sch.col_Start.Date).Days);
                        sch.col_Stop = sch.col_Stop.AddDays((selectedDate.Date - sch.col_Stop.Date).Days);
                    }
                    // This schedule record matches - update local data
                    sch.bFilterEmployeeID = true;
                    sch.bFilterRoleID = true;
                    sch.bFilterStart = true;
                    sch.bFilterStop = true;
                    sch.bFilterRecurrenceType = true;
                    sch.bFilterPreference = true;
                    ScheduleRecords.Add(sch);
                }
            }
            // Load roles for this employee
            cmbRole.Visibility = Visibility.Visible;
            lblRole.Visibility = Visibility.Visible;
            btnNote.Visibility = Visibility.Visible;
            cmbRole.Items.Clear();
            EmployeeRoleRecords.Clear();
            btnAddSchedule.Visibility = Visibility.Visible;
            lblSchedules.Visibility = Visibility.Visible;
            foreach (ServiceReferenceOpenRPOS.Role role in Globals.db.RoleRecords)
                foreach (ServiceReferenceOpenRPOS.EmployeeRole empRole in Globals.db.EmployeeRoleRecords)
                    if (empRole.col_RoleID == role.col_ID && empRole.col_EmployeeID == currentEmployeeID)
                    {
                        // Add this role
                        EmployeeRoleRecords.Add(empRole);
                        cmbRole.Items.Add(role.col_Title);
                        // Determine if this is the role for this schedule record
                        if (ScheduleRecords.Count > 0)
                            if (empRole.col_RoleID == ScheduleRecords[0].col_RoleID)
                                cmbRole.SelectedIndex = cmbRole.Items.Count - 1;
                    }
            // Initialize the start/stop times
            tpIn.Value = currentDate;
            tpOut.Value = currentDate;
            cbRecurrence.IsChecked = false;
            // If there are any records, display this information
            if (ScheduleRecords.Count > 0)
            {
                initDisplay();
            }
            else // If no records were found, disable the interface
            {
                clearDisplay();
            }
        }

        public void initScheduleTemplate(int scheduleTemplateID, DateTime selectedDate)
        {
            currentScheduleTemplateID = scheduleTemplateID;
            currentEmployeeID = 0;
            currentDate = selectedDate;
            ScheduleRecords.Clear();
            IEnumerable<ServiceReferenceOpenRPOS.Schedule> query = Globals.db.ScheduleRecords.OrderBy(sch => sch.col_Start);
            // Set the date
            lblDate.Content = selectedDate.DayOfWeek.ToString().Substring(0, 3);
            // Get schedule for that day
            foreach (ServiceReferenceOpenRPOS.Schedule sch in query)
            {
                if (sch.col_ScheduleTemplateID == currentScheduleTemplateID && sch.col_Start.Date.DayOfWeek == selectedDate.Date.DayOfWeek)
                {
                    // Reset the date for recurrence records
                    if (sch.col_RecurrenceType == 1)
                    {
                        sch.col_Start = sch.col_Start.AddDays((selectedDate.Date - sch.col_Start.Date).Days);
                        sch.col_Stop = sch.col_Stop.AddDays((selectedDate.Date - sch.col_Stop.Date).Days);
                    }
                    // This schedule record matches - update local data
                    sch.bFilterEmployeeID = true;
                    sch.bFilterScheduleTemplateID = true;
                    sch.bFilterRoleID = true;
                    sch.bFilterStart = true;
                    sch.bFilterStop = true;
                    sch.bFilterRecurrenceType = true;
                    sch.bFilterPreference = true;
                    ScheduleRecords.Add(sch);
                }
            }
            // Ignore roles for templates
            cmbRole.Visibility = Visibility.Collapsed;
            lblRole.Visibility = Visibility.Collapsed;
            btnNote.Visibility = Visibility.Collapsed;
            cmbRole.Items.Clear();
            EmployeeRoleRecords.Clear();
            btnAddSchedule.Visibility = Visibility.Visible;
            lblSchedules.Visibility = Visibility.Visible;
            // Initialize the start/stop times
            tpIn.Value = currentDate;
            tpOut.Value = currentDate;
            cbRecurrence.IsChecked = false;
            // If there are any records, display this information
            if (ScheduleRecords.Count > 0)
            {
                initDisplay();
            }
            else // If no records were found, disable the interface
            {
                clearDisplay();
            }
        }

        private void updateCurrentRecord()
        {
            // Update current record
            ScheduleRecords[currentSchedule].col_EmployeeID = currentEmployeeID;
            ScheduleRecords[currentSchedule].col_ScheduleTemplateID = currentScheduleTemplateID;
            ScheduleRecords[currentSchedule].col_RoleID = (currentEmployeeID == 0) ? 0 : EmployeeRoleRecords[cmbRole.SelectedIndex].col_RoleID;
            ScheduleRecords[currentSchedule].col_Start = (DateTime)tpIn.Value;
            ScheduleRecords[currentSchedule].col_Stop = (DateTime)tpOut.Value;
            ScheduleRecords[currentSchedule].col_RecurrenceType = ((bool)cbRecurrence.IsChecked) ? (short)1 : (short)0;
            ScheduleRecords[currentSchedule].col_Preference = !Globals.currentLogin.col_Manager;
            
            ScheduleRecords[currentSchedule].bFilterEmployeeID = true;
            ScheduleRecords[currentSchedule].bFilterScheduleTemplateID = true;
            ScheduleRecords[currentSchedule].bFilterRoleID = true;
            ScheduleRecords[currentSchedule].bFilterStart = true;
            ScheduleRecords[currentSchedule].bFilterStop = true;
            ScheduleRecords[currentSchedule].bFilterRecurrenceType = true;
            ScheduleRecords[currentSchedule].bFilterPreference = true;
        }

        public async Task<int> save()
        {
            ObservableCollection<ServiceReferenceOpenRPOS.Schedule> tempScheduleRecords = new ObservableCollection<ServiceReferenceOpenRPOS.Schedule>();
            bool clearRecord=false;

            // Remove any exiting schedule records for this employee for this day
            foreach (ServiceReferenceOpenRPOS.Schedule sch in Globals.db.ScheduleRecords)
            {
                if (currentEmployeeID == 0) // Must be a template record
                {
                    clearRecord = (sch.col_ScheduleTemplateID == currentScheduleTemplateID && sch.col_Start.DayOfWeek == currentDate.DayOfWeek);
                }
                else
                {
                    clearRecord = (sch.col_EmployeeID == currentEmployeeID && sch.col_Start.ToShortDateString() == currentDate.ToShortDateString()
                        && !sch.col_Preference && sch.col_ScheduleTemplateID == 0);
                }
                if (clearRecord)
                {
                    await Globals.db.DeleteScheduleObject(sch);
                    tempScheduleRecords.Add(sch);
                }
            }
            // Clear schedule records from global collection
            foreach (ServiceReferenceOpenRPOS.Schedule sch in tempScheduleRecords)
                Globals.db.ScheduleRecords.Remove(sch);

            // Update current record
            if(ScheduleRecords.Count>0) updateCurrentRecord();
            
            // Update the database with the new schedules
            foreach (ServiceReferenceOpenRPOS.Schedule sch in ScheduleRecords)
            {
                sch.col_ID = await Globals.db.AddScheduleObject(sch);
                // Update global schedule information
                Globals.db.ScheduleRecords.Add(sch);
            }

            return 0;
        }

        private void btnAddSchedule_Click(object sender, RoutedEventArgs e)
        {
            // Update current record (if exists)
            if(ScheduleRecords.Count>0) updateCurrentRecord();
            // Add a new schedule record
            ServiceReferenceOpenRPOS.Schedule sch = new ServiceReferenceOpenRPOS.Schedule();
            sch.col_Start = currentDate;
            sch.col_Stop = currentDate;
            sch.col_RoleID = (EmployeeRoleRecords.Count > 0) ? EmployeeRoleRecords[0].col_RoleID : 0;
            ScheduleRecords.Add(sch);
            currentSchedule = ScheduleRecords.Count - 1;
            initDisplay();                
        }

        private void btnPrevSchedule_Click(object sender, RoutedEventArgs e)
        {
            // Update current record
            updateCurrentRecord();
            // Navigate to the previous schedule record
            currentSchedule--;
            // Populate the display with the schedule record information for this schedule
            initDisplay();
        }

        private void btnNextSchedule_Click(object sender, RoutedEventArgs e)
        {
            // Update current record
            updateCurrentRecord();
            // Navigate to the next schedule record
            currentSchedule++;
            // Populate the display with the schedule record information for this schedule
            initDisplay();
        }

        private void btnDeleteSchedule_Click(object sender, RoutedEventArgs e)
        {
            // Delete the selected schedule record
            ScheduleRecords.RemoveAt(currentSchedule);
            currentSchedule = (currentSchedule > ScheduleRecords.Count - 1) ? ScheduleRecords.Count - 1 : currentSchedule;
            if (currentSchedule < 0) { currentSchedule = 0; clearDisplay(); } else initDisplay();
        }

        private void tpOut_ValueChanged(object sender, RoutedPropertyChangedEventArgs<DateTime?> e)
        {
            // Ensure stop>=start
            if (tpOut.Value < tpIn.Value) tpIn.Value = tpOut.Value;
        }

        private void tpIn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<DateTime?> e)
        {
            // Ensure start<=stop
            if (tpIn.Value > tpOut.Value) tpOut.Value = tpIn.Value;
        }

        private void btnNote_Click(object sender, RoutedEventArgs e)
        {
            EditNoteDialog end = new EditNoteDialog();
            end.init(currentEmployeeID, currentDate);
            end.Show();
        }

    }
}
